package bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DefaultBeanFactory implements BeanFactory{
    /**
     * 对象信息 map
     */
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    /**
     * 注册对象定义信息
     * @param beanName        bean 名称
     * @param beanDefinition  对象定义信息
     */
    public void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {
        // 这里可以添加监听器
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    /**
     * 对象 map
     */
    private Map<String, Object> beanMap = new ConcurrentHashMap<>();
    /**
     * 根据名称获取对应的实例信息
     *
     * @param beanName bean 名称
     * @return 对象信息
     */
    @Override
    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if(bean != null) {
            // 这里直接返回的是单例，如果用户指定为多例，则每次都需要新建。
            return bean;
        }

        // 获取对应配置信息
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition == null) {
            throw new RuntimeException(beanName + " not exists in bean define.");
        }

        // 直接根据
        Object newBean = createBean(beanDefinition);
        // 这里可以添加对应的监听器
        beanMap.put(beanName, newBean);
        return newBean;
    }
    /**
     * 根据对象定义信息创建对象
     * @param beanDefinition 对象定义信息
     * @return 创建的对象信息
     * @since 0.0.1
     */
    private Object createBean(final BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getBeanClass();
        try {
            // 尝试获取无参构造器
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(true);
            return constructor.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }catch (NoSuchMethodException | InvocationTargetException e) {
            throw new RuntimeException("Class " + clazz.getName() + " lacks no-arg constructor", e);
        }
    }
    /**
     * 获取指定类型的实现
     *
     * @param beanName 属性名称
     * @param tClass   类型
     * @return 结果
     */
    @Override
    public <T> T getBean(String beanName, Class<T> tClass) {
        return null;
    }
}
